ЛЕКЦИЯ 9

Файлы

 

Ввод и вывод: файлы

Процесс ввода с консоли весьма трудоемок, а результат вывода на консоль - недолговечен. Однако, существует более удобный способ записывать, хранить, пересылать и по необходимости считывать информацию из постоянной памяти компьютера. Для этого применяются файлы.

 

Файл

Файл - это самостоятельная последовательность символов, записанная в постоянную память компьютера.

 

В английском языке слово "file" имеет вполне понятный смысл: "вереница", что очень хорошо отражает внутреннюю структуру любого файла. Файл - это именно вереница символов, причем связанных в определенной последовательности: символы файла не могут по своему желанию перепрыгивать с одного места на другое.

 

"Самостоятельность" файлов заключается в том, что они не зависят от работы какой-либо программы. И даже если выключить компьютер, файлы будут продолжать свое существование на винчестере или на дискете.

 

Файлы могут хранить в себе все, что поддается кодированию:

 

 

Когда нужно использовать файлы

 

Выбор между консолью и файлами вам придется делать каждый раз, когда вы станете писать очередную программу.

 

 

Например, если вашей программе необходимо получить два или три числа (пять - уже многовато) или строку длиной символов десять, вы вполне можете задавать такие данные с клавиатуры вручную. Если же вам (а еще вероятнее - не вам, а некоему усредненному и потому посредственному оператору) придется вводить, скажем, массив чисел 10х10, то вероятность ошибки при ручном вводе возрастает многократно. Значит, возможность этой ошибки нужно исключить: записать данные в файл, который легко отредактировать в случае необходимости. Кроме того, однажды созданный файл можно использовать многократно (может быть, с незначительными изменениями).

 

Разновидности файлов

 

В языке Pascal имеется возможность работы с тремя видами файлов:

 

 

Последние два типа объединяются под названием бинарные: информация в них записывается по байтам и потому не доступна для просмотра или редактирования в удобных для человека текстовых редакторах, зато такие файлы более компактны, чем текстовые.

 

В отличие от бинарных, текстовые файлы возможно создавать, просматривать и редактировать "вручную" - в любом доступном текстовом редакторе. Кроме того, при считывании данных из текстового файла нет необходимости заботиться об их преобразовании: в языке Pascal имеются средства автоматического перевода содержимого текстовых файлов в нужный тип и формат, и это позволяет сэкономить немало времени и сил.

 

Описание файлов

 

В разделе var переменные, используемые для работы с файлами (файловые переменные), описываются следующим образом:

var f1,f2: text;                                                  {текстовые файлы}

   g: file of <тип_элементов_файла>;   {типизированные файлы}

   in, out: file;                                                   {нетипизированные файлы}

 

Файловая переменная не может быть задана константой.

 

Текстовые файлы

 

С этого момента и до конца раздела «Текстовые файлы» под словом "файл" мы будем подразумевать "текстовый файл" (разумеется, если специально не оговорено обратное). Однако многие описываемые ниже команды пригодны не только для текстовых, но и для бинарных файлов.

 

Назначение файла

 

Процедура assign(f,'<имя_файла>'); служит для установления связи между файловой переменной f и именем того файла, за действия с которым эта переменная будет отвечать.

 

На разных этапах работы программы одной и той же файловой переменной можно присваивать разные значения. Например, если в начале программы мы напишем

 

assign(f,'input.txt');

 

то переменной f будет соответствовать файл, из которого производится считывание входных данных, вплоть до того момента, когда в программе встретится, скажем, команда

 

 assign(f,'output.txt');

 

после которой переменной f будет уже соответствовать тот файл, куда выводятся результаты.

 

Строка '<имя_файла>' может содержать полный путь к файлу. Если путь не указан, файл считается расположенным в той же директории, что и исполняемый модуль программы. Именно этот вариант обычно считается наиболее удобным.

 

 

Открытие файла

 

В зависимости от того, какие действия ваша программа собирается производить с открываемым файлом, возможно троякое его открытие:

 

reset(f);

- открытие файла для считывания из него информации; если такого файла не существует, попытка открыть его вызовет ошибку и аварийную остановку работы программы. Эта же команда служит для возвращения указателя на начало файла;

 

rewrite(f);

- открытие файла для записи в него информации; если такого файла не существует, он будет создан; если файл с таким именем уже есть, вся содержавшаяся в нем ранее информация исчезнет;

append(f);

- открытие файла для записи в него информации (указатель помещается в конец этого файла). Если такого файла не существует, он будет создан; а если файл с таким именем уже есть, вся содержащаяся в нем ранее информация будет сохранена, потому что запись будет производиться в его конец.

 

Закрытие файла

 

После того как ваша программа закончит работу с файлом, очень желательно закрыть его:

 

close(f);

 

В противном случае информация, содержащаяся в этом файле, может быть потеряна.

 

Считывание из файла

 

Чтение данных из файла, открытого для считывания, производится с помощью команд read() и readln(). В скобках сначала указывается имя файловой переменной, а затем - список ввода. Например:

 

read(f,a,b,c);

- читать из файла f три переменные a, b и c. После выполнения этой процедуры указатель в файле передвинется за переменную с;

readln(f,a,b,c);

- читать из файла f три переменные a, b и c, а затем перевести указатель ("курсор") на начало следующей строки; если кроме уже считанных переменных в строке содержалось еще что-то, то этот "хвост" будет проигнорирован.

 

Если вспомнить, что в памяти компьютера любой файл записывается линейной последовательностью символов и никакой разбивки на строки там реально нет, то действия процедуры readln() можно пояснить так: читать все указанные переменные, а затем игнорировать все символы вплоть до ближайшего символа "конец строки" или "конец файла". Указатель при этом перемещается на позицию непосредственно за первым найденным символом "конец строки".

 

Если же символ конца строки встретится где-нибудь между переменными, указанными в списке ввода, то обе процедуры его просто проигнорируют.

 

Считывать из текстового файла можно только переменные простых типов: целых, вещественных, символьных, - а также строковых. Численные переменные, считываемые из файла, должны разделяться хотя бы одним пробельным символом. Типы вводимых данных и типы тех переменных, куда эти данные считываются, обязаны быть совместимыми. Здесь действуют все те же правила, что и при считывании с клавиатуры.

 

 

 

 

 

 

 

Считываемые переменные могут иметь различные типы. Например, если в файле f записана строка

 

1 2.5 с

 

то командой read(f,a,b,c,c); можно прочитать одновременно значения для трех переменных, причем все - разных типов:

 

a: byte;

b: real;

c: char;

 

Замечание: Обратите внимание, что символьную переменную c пришлось считывать дважды, так как после числа "2.5" сначала идет символ пробела и только затем буква "c".

 

Из файла невозможно считать переменную составного типа (например, если а - массив, то нельзя написать read(f,a), можно ввести его только поэлементно, в цикле), файлового, а также логического.

 

Особенно внимательно нужно считывать строки (string[length] и string): эти переменные "забирают" из файла столько символов, сколько позволяет им длина (либо вплоть до ближайшего конца строки). Если строковая переменная неопределенной длины (тип данных string) является последней в текущей строке файла, то никаких проблем с ее считыванием не возникнет. Но в случае, когда необходимо считывать переменную типа string из начала или из середины строки файла, это придется делать с помощью цикла - посимвольно. Аналогичным образом - посимвольно, от пробела до пробела - считываются из текстового файла слова.

 

Есть еще один, гораздо более трудоемкий способ: считать из файла всю строку целиком, а затем "распотрошить" ее - разобрать на части специальной процедурой выделения подстрок copy(). После чего (где необходимо) применить процедуру превращения символьной записи числа в само число, применяя стандартную процедуру val(). Кроме того, совсем не очевидно, что длина вводимой строки не будет превышать 256 символов, поэтому такой способ приходится признать неудовлетворительным.

 

Запись в файл

Сохранять переменные в файл, открытый для записи командами rewrite(f) или append(f), можно при помощи команд write() и writeln(). Так же как в случае считывания, первой указывается файловая переменная, а за ней - список вывода:

 

write(f,a,b,c);

- записать в файл f переменные a,b и c;

writeln(f,a,b,c);

- записать в файл f переменные a, b и c, а затем записать туда же символ "конец строки".

 

Выводить в текстовый файл можно переменные любых базовых типов (вместо значений логического типа выведется их строковый аналог TRUE или FALSE) или строки.

 

Структурированные типы данных можно записывать только поэлементно.

 

Пробельные символы

К пробельным символам (присутствующим в файле, но невидимым на экране) относятся:

 

Замечание: Пара символов #13 и #10 является признаком конца строки текстового файла (в кодировках DOS и Windows).

 

В (текстовом) файле границами чисел служат пробельные символы, и при считывании чисел эти пробельные символы игнорируются, сколько бы их ни было. Таким образом, если ввод многих чисел производится с помощью команды read(), то нет никакой разницы, как именно записаны эти числа: в одну строку, в несколько строк или вовсе в один столбик. В любом случае считывание пройдет корректно и завершится только по достижении конца файла.

 

Если же считывание тестового файла производится посимвольно, то нужно аккуратно отслеживать пробельные (особенно концевые) символы.

 

Поиск специальных пробельных символов (нас интересуют в основном #10, #13 и #26) можно осуществлять при помощи стандартных функций:

 

eof(f) - возвращает значение TRUE, если уже достигнут конец файла f (указатель находится сразу за последним элементом файла), и FALSE в противном случае;

 

seekeof(f) - возвращает значение TRUE, если "почти" достигнут конец файла f (между указателем и концом файла нет никаких символов, кроме пробельных), и FALSE в противном случае;

 

eoln(f) - возвращает значение TRUE, если достигнут конец строки в файле f (указатель находится сразу за последним элементом строки), и FALSE в противном случае;

 

seekeoln(f) - возвращает значение TRUE, если "почти" достигнут конец строки в файле f (между указателем и концом строки нет никаких символов, кроме пробельных), и FALSE в противном случае.

 

Ясно, что в большинстве случаев предпочтительнее использовать функции seekeof(f) и seekeoln(f): они предназначены специально для текстовых файлов, игнорируют концы строк (и вообще все пробельные символы) и потому позволяют автоматически обработать сразу несколько частных случаев.

 

Например, если по условию задачи файл входных данных может содержать только одну строку, то правильнее всего будет написать программу, обрабатывающую все возможные варианты:

 

Поскольку функции seekeof() и seekeoln() при каждой проверке пытаются проигнорировать все пробельные символы, то и результаты их работы отличаются от результатов работы функций eof() и eoln(). Эти различия нужно учитывать.

 

 

 

 

 

 

 

 

Например, для входного файла f, состоящего из двух строк 1_2_ _3_#13#10 (всего 9 символов, вторая строка пустая, подчеркивания здесь обозначают пробелы), следующие куски программ будут выдавать такие результаты:

Код

Содержимое

результирующего файла g

Длина файла g

while not eof(f) do

begin read(f,c); {c: char}

      write(g,c)

end;

1_2_ _3_#13#10

9 байт

while not seekeof(f) do

begin read(f,c); {c: char}

      write(g,c)

end;

123

3 байта

while not eof(f) do

while not seekeoln(f) do

begin read(f,c); {c: char}

      write(g,c)

end;

Зацикливание

 

while not seekeof(f) do

while not eoln(f) do

begin read(f,c); {c: char}

      write(g,c)

end;

1_2_ _3_

7 байт

while not seekeof(f) do

while not  eoln(f) do

begin read(f,k); {k: byte}

      write(g,k)

end;

1230

4 байта

 

Пример использования файлов

 

Задача. В текстовом файле f.txt записаны (вперемешку) целые числа: поровну отрицательных и положительных. Используя только один вспомогательный файл, переписать в текстовый файл h.txt все эти числа так, чтобы:

 

Решение

 

Если бы нам разрешили использовать два вспомогательных файла, мы бы просто переписали все положительные числа в один из них, а все отрицательные - в другой. А затем объединили бы два этих файла. В нашем же случае придется переписать во вспомогательный файл только положительные числа. Затем при "сборке" мы будем считывать из вспомогательного файла "все подряд", а из исходного - только отрицательные числа.

 

Реализация

 

program z1;

var f,g,h: text;

    k: integer;

begin

      assign(f,'f.txt');

      assign(g,'g.txt');

      assign(h,'h.txt');

{Переписываем положительные числа в допайл}

      reset(f);

      rewrite(g);

      while not eof(f) do

         begin read(f,k);

               if k>0 then write(g,k,' ');

         end;

{Собираем числа в новый файл h.txt}

      reset(f); {Возвращаем указатель на начало файла f}

      reset(g);

      rewrite(h);

      while not eof(g) do

          begin read(g,k);

               write(h,k,' ');

               repeat

                  read(f,k)

               until k<0;

               write(h,k,' ');

         end;

            close(f);

   close(g);

   close(h);

end.

 

Изменение реакции на ошибку

 

По умолчанию любая ошибка ввода или вывода вызывает аварийную остановку работы программы. Однако существует возможность отключить такое строгое реагирование; в этом случае программа сможет либо игнорировать эти ошибки (что, правда, далеко не лучшим образом отразится на результатах ее работы), либо обрабатывать их при помощи системной функции IOResult: integer.

 

Директива компилятора1) {$I-} отключает режим проверки, соответственно директива {$I+} - включает.

 

Если при отключенной проверке правильности ввода-вывода ({$I-}) происходит ошибка, то все последующие операции ввода-вывода игнорируются - вплоть до первого обращения к функции IOResult. Ее вызов "очищает" внутренний показатель ("флаг") ошибки, после чего можно продолжать ввод или вывод.

 

Если функция IOResult возвращает 0, значит, операция ввода-вывода была завершена успешно. В противном случае функция вернет номер произошедшей ошибки.

 

Пример использования директив {$I}

 

flag:= false;

write('Введите имя файла: ');

repeat

      readln(s);    {s:string}

{$I-}

      assign(f,s);

      reset(f);

      case IOResult of

            0: flag:= true;

            3: write('Путь к файлу указан неверно. Измените путь: ');

            5: write('Доступа к файлу нет. Измените имя файла: ');

         152: write('Такого диска нет. Измените имя диска: ');

         else write('Такого файла нет. Измените имя файла: ');

      end;

   until flag;

{$I+}

 

Номер ошибки

Описание ошибки

Генерирующие процедуры

2

File not found

Файл не найден

append, erase, rename, reset, rewrite

3

Path not found

Директория не найдена

append, chdir, erase, mkdir, rename, reset, rewrite, rmdir

4

Too many open files

Открыто более 15 файлов одновременно

append, reset, rewrite

5

File access denied

Отказ в доступе к файлу

append, blockread, blockwrite, erase, mkdir, read, readln, rename, reset, rewrite, rmdir, write, writeln

12

Invalid file access code

Попытка использовать текстовый файл как типизированный или наоборот

append, reset

16

Cannot remove current directory

Невозможно удалить заданную директорию

rmdir

100

Disk read error

Попытка чтения после конца файла

read, readln

101

Disk write error

Ошибка записи на диск (диск полон)

close, write, writeln

102

File not assigned

Файл не назначен

append, erase, rename, reset, rewrite

103

File not open

Файл не открыт{бинарные файлы}

blockread, blockwrite, close, eof, filepos, filesize, read, seek, write

104

File not open for input

Файл не открыт для ввода {текстовые файлы}        

eof, eoln, read, readln, seekeof, seekeoln

105

File not open for output

Файл не открыт для вывода {текстовые файлы}

write, writeln

106

Invalid numeric format

Неправильный числовой формат {текстовые файлы}

read, readln

152

Drive not ready

Задано неверное имя диска

append, erase, rename, reset, rewrite

 

Бинарные файлы

 

Бинарные файлы хранят информацию в том виде, в каком она представлена в памяти компьютера, и потому неудобны для человека. Заглянув в такой файл, невозможно понять, что в нем записано; его нельзя создавать или исправлять вручную - в каком-нибудь текстовом редакторе - и т.п. Однако все эти неудобства компенсируются скоростью работы с данными.

 

Кроме того, текстовые файлы относятся к структурам последовательного доступа, а бинарные - прямого. Это означает, что в любой момент времени можно обратиться к любому, а не только к текущему элементу бинарного файла.

 

Типизированные файлы

 

Переменные структурированных типов данных (кроме строкового) невозможно считать из текстового файла. Например, если нужно ввести из текстового файла данные для наполнения записи toy информацией об имеющихся в продаже игрушках (название товара, цена товара и возрастной диапазон, для которого игрушка предназначена):

 

      type toy = record name: string[20];

                  price: real;

                  age: set of 0..18;      {в файле задано границами}

      end;

 

то придется написать следующий код:

 

var f: text;

         c: char;

         i,j,min,max: integer;

         a: array[1..100] of toy;

begin

   assign(f,input);

   reset(f);

   for i:=1 to 100 do

      if not eof(f)

          then with a[i] do

                 begin readln(f,name,price,min,max);

                        age:=[];

                        for j:= min to max do age:=age+[j];

                 end;

   close(f);

   ...

end.

 

Как видим, такое поэлементное считывание весьма неудобно и трудоемко.

 

Выход из этой ситуации предлагают типизированные файлы - их элементы могут относиться к любому базовому или структурированному типу данных. Единственное ограничение: все элементы должны быть одного и того же типа. Это кажущееся неудобство является непременным условием для организации прямого доступа к элементам бинарного файла: как и в случае массивов, если точно известна длина каждого компонента структуры, то адрес любого компонента может быть вычислен по очень простой формуле:

 

<начало_структуры> + <номер_компонента>*<длина_компонента>

 

Описание типизированных файлов

 

В разделе var файловые переменные, предназначенные для работы с типизированными файлами, описываются следующим образом:

 

var <файловая_перем>: file of <тип_элементов_файла>;

 

Никакая файловая переменная не может быть задана константой.

 

Назначение типизированного файла

 

С этого момента и до конца раздела под словом "файл" мы будем подразумевать "бинарный типизированный файл" (разумеется, если специально не оговорено иное).

 

Команда assign(f,'<имя_файла>'); служит для установления связи между файловой переменной f и именем того файла, за работу с которым эта переменная будет отвечать.

 

Строка '<имя_файла>' может содержать полный путь к файлу. Если путь не указан, файл считается расположенным в той же директории, что и исполняемый модуль программы.

 

Открытие и закрытие типизированного файла

 

В зависимости от того, какие действия ваша программа собирается производить с открываемым файлом, возможно двоякое его открытие:

 

reset(f);

- открытие файла для считывания из него информации и одновременно для записи в него (если такого файла не существует, попытка открытия вызовет ошибку). Эта же команда служит для возвращения указателя на начало файла;

rewrite(f);

- открытие файла для записи в него информации; если такого файла не существует, он будет создан; если файл с таким именем уже есть, вся содержавшаяся в нем ранее информация исчезнет.

 

Закрываются типизированные файлы процедурой close(f), общей для всех типов файлов.

 

Считывание из типизированного файла

 

Чтение из файла, открытого для считывания, производится с помощью команды read(). В скобках сначала указывается имя файловой переменной, а затем - список ввода:

 

read(f,a,b,c); - читать из файла f три однотипные переменные a, b и c.

 

Вводить из файла можно только переменные соответствующего объявлению типа, но этот тип данных может быть и структурированным. Cкажем, если вернуться к примеру, приведенному в начале п. "Типизированные файлы", то станет очевидным, что использование типизированного файла вместо текстового позволит значительно сократить текст программы:

 

type toy = record name: string[20];

                     price: real;

                     age: set of 0..18;        {задано границами}

             end;

var f: file of toy;

   a: array[1..100] of toy;

begin

   assign(f,input);

   reset(f);

   for i:=1 to 100 do

   if not eof(f) then read(f,a[i]);

   close(f);

   ...

end.

 

Поиск в типизированном файле

 

Функция eof(f:file):boolean сообщает о достигнутом конце файла. Все остальные функции "поиска конца" (eoln(), seekeof() и seekeoln()), свойственные текстовым файлам, нельзя применять к файлам типизированным.

 

Зато существуют специальные подпрограммы, которые позволяют работать с типизированными файлами как со структурами прямого доступа:

 

  1. Функция filepos(f:file):longint сообщит текущее положение указателя в файле f. Если он указывает на самый конец файла, содержащего N элементов, то эта функция выдаст результат N. Это легко объяснимо: элементы файла нумеруются начиная с нуля, поэтому последний элемент имеет номер N-1. А номер N принадлежит, таким образом, "несуществующему" элементу - признаку конца файла.
  2. Функция filesize(f:file):longint вычислит длину файла f.
  3. Процедура seek(f:file,n:longint) передвинет указатель в файле f на начало записи с номером N. Если окажется, что n больше фактической длины файла, то указатель будет передвинут и за реальный конец файла.
  4. Процедура truncate(f:file) обрежет "хвост" файла f: все элементы начиная с текущего и до конца файла будут из него удалены. На самом же деле произойдет лишь переписывание признака "конец файла" в то место, куда указывал указатель, а физически "отрезанные" значения останутся на прежних местах - просто они станут "бесхозными".

 

Запись в типизированный файл

 

Сохранять переменные в файл, открытый для записи, можно при помощи команды write(). Так же как и в случае считывания, первой указывается файловая переменная, а за ней - список вывода:

 

write(f,a,b,c); - записать в файл f (предварительно открытый для записи командами rewrite(f) или reset(f)) переменные a,b,c.

 

Выводить в типизированный файл можно только переменные соответствующего описанию типа данных. Неименованные и нетипизированные константы нельзя выводить в типизированный файл.

 

Типизированные файлы рассматриваются как структуры одновременно и прямого, и последовательного доступа. Это означает, что запись возможна не только в самый конец файла, но и в любой другой его элемент. Записываемое значение заместит предыдущее значение в этом элементе (старое значение будет "затерто").

 

Например, если нужно заместить пятый элемент файла значением, хранящимся в переменной а, то следует написать следующий отрывок программы:

 

seek(f,5); {указатель будет установлен на начало 5-го элемента}

 

write(f,a); {указатель будет установлен на начало 6-го элемента}

 

Замечание: Поскольку и чтение из файла, и запись в файл сдвигают указатель на следующую позицию, то в случае, когда необходимо сначала прочитать значение, хранящееся в каком-то элементе, а затем вписать на это место новые данные, необходимо производить поиск дважды:

 

seek(f,5); {указатель - на начало 5-го элемента}

 

read(f,a); {указатель - на начало 6-го элемента}

 

seek(f,5); {указатель - на начало 5-го элемента}

 

write(f,b); {указатель - на начало 6-го элемента}

 

А что произойдет, если в файле содержится всего N элементов, а запись производится в (N+k)-й? Тогда начало файла останется прежним, затем в файл будет включен весь тот "мусор", что оказался между его концом и записываемой переменной, и, наконец, последним элементом нового файла станет записанное значение.

 

Нетипизированные файлы

 

Главное преимущество нетипизированных файлов - это высокая скорость их обработки. Открыть как нетипизированный можно и файл любой другой природы: текстовый или бинарный типизированный. В основном это применяется в тех случаях, когда нужно перекопировать довольно большой кусок одного файла в другой без изменений.

 

Описание нетипизированных файлов

 

В разделе var файловые переменные, предназначенные для работы с нетипизированными файлами, описываются следующим образом:

 

var g: file;

 

Никакая файловая переменная не может быть задана константой.

 

Назначение нетипизированного файла

 

Содержимое этого раздела дословно повторяет все сказанное в разделе "Назначение типизированного файла".

 

Открытие и закрытие нетипизированного файла

 

В зависимости от того, какие действия ваша программа собирается производить с открываемым файлом, возможно двоякое его открытие:

 

reset(f[,size]);

- открытие файла для считывания из него информации и одновременно для записи в него (если такого файла не существует, попытка открытия вызовет ошибку). Эта же команда служит для возвращения указателя на начало файла;

rewrite(f[,size]);

- открытие файла для записи в него информации; если такого файла не существует, он будет создан; если файл с таким именем уже есть, вся содержавшаяся в нем ранее информация исчезнет.

 

Необязательная переменная size может задать количество байтов, единовременно считываемых из нетипизированного файла или записываемых в него. По умолчанию размер таких "кусков" принимается равным 128 байт.

 

Закрываются нетипизированные файлы процедурой close(f), общей для всех типов файлов.

 

Поиск в нетипизированном файле

 

Все подпрограммы, описанные в разделе "Поиск в типизированном файле", будут работать и для нетипизированного файла. Но, поскольку тип элементов нетипизированного файла не определен, то размер одного "элемента" принимается равным 128 байт (по умолчанию) или указанному в переменной size во время открытия файла.

 

Запись и чтение

 

Для осуществления записи в нетипизированный файл и считывания из него применяются две специальные процедуры blockread() и blockwrite().

 

blockread(f:file; buf,count:word [;result:word]);

Процедура предназначена для считывания из файла f нескольких элементов разом (их количество указывается в переменной count, а длина устанавливается во время открытия файла) при помощи буфера обмена данными buf. Необязательная переменная result может хранить количество элементов, фактически считанных из файла.

blockwrite(f:file; buf,count:word [;result:word]);

Процедура производит запись данных в нетипизированный файл при помощи буфера buf.

 

 

Подпрограммы обработки директорий

 

Приведем здесь также несколько стандартных процедур, осуществляющих работу с директориями, а также с файлами, но внешним относительно самих файлов образом (без их открытия).

 

Процедура erase(f: file) удалит файл, связанный с файловой переменной f. Если такого файла нет, произойдет ошибка, реакцию на которую можно отрегулировать при помощи директивы компилятора {$I} (см. лекцию 6).

 

Процедура rename(f: file; s: string) даст файлу, связанному с файловой переменной f, новое имя, указанное в строке s. Если такого файла нет, произойдет ошибка.

 

Процедура chdir(s: string) сделает текущей директорию, указанную в строке s. Если такой директории нет, произойдет ошибка.

 

Процедура getdir(disk: byte; s:string) запишет в строку s имя текущей директории на указанном диске (0 - текущий диск, 1 - диск А , 2 - диск В и т.д.).

 

Процедура mkdir(s: string) создаст в текущей директории новую поддиректорию с указанным в строке s именем. Если в текущей директории уже существуют файл или директория с указанным именем, произойдет ошибка.

 

Процедура rmdir(s: string) удалит пустую директорию с заданным в строке s именем. Если такой директории нет, произойдет ошибка.

Применимость подпрограмм обработки файлов

 

Сведем информацию о применимости процедур и функций работы с файлами в единую таблицу.

 

Текстовые

Типизированные

Нетипизированные

append

+

 

 

assign

+

+

+

blockread

 

 

+

blockwrite

 

 

+

close

+

+

+

eof

+

+

+

eoln

+

 

 

filepos

 

+

+

filesize

 

+

+

read

+

+

 

readln

+

 

 

reset

+

+

+

rewrite

+

+

+

seek

 

+

+

seekeof

+

 

 

seekeoln

+

 

 

truncate

 

+

+

write

+

+

 

writeln

+

 

 

 

Замечание: Реакция на ошибку, возникающую при выполнении любой из перечисленных здесь подпрограмм, зависит от состояния директивы компилятора {$I}.